// Copyright (C) 1953-2022 NUDT
// Verilog module name - packet_descriptor_extract
// Version: V3.4.0.20220225
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         descriptor extract
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module packet_descriptor_extract #(parameter inport = 6'b0000)
(
        i_clk,
        i_rst_n,
       
        iv_data,
        i_data_wr,
		//iv_ipv,
        //iv_eth_type,
        
        ov_data,
        o_data_wr,
        o_descriptor_valid,
        ov_descriptor,
        ov_eth_type,
        ov_tsmp_subtype,
        
        descriptor_extract_state
    );
// I/O
// clk & rst
input                   i_clk;
input                   i_rst_n;
//input
input       [8:0]       iv_data;
input                   i_data_wr;
//input       [2:0]       iv_ipv;
//input       [15:0]      iv_eth_type;
//output
output  reg [8:0]       ov_data;
output  reg             o_data_wr;
output  reg             o_descriptor_valid;
output  reg [11:0]      ov_descriptor;
output  reg [15:0]      ov_eth_type;
output  reg [7:0]       ov_tsmp_subtype;

output  reg [3:0]       descriptor_extract_state;
//internal wire
reg         [3:0]       rv_byte_cnt; 
localparam  IDLE_S              = 4'd0,
            EXTRACT_INFO_S      = 4'd1,
            TRAN_PKT_S          = 4'd2;
            
always@(posedge i_clk or negedge i_rst_n)
    if(!i_rst_n) begin
        ov_data                          <= 9'b0 ;
        o_data_wr                        <= 1'b0 ;
        o_descriptor_valid               <= 1'b0 ;
        ov_descriptor                    <= 12'b0;
        rv_byte_cnt                      <= 4'b0 ;
        ov_eth_type                      <= 16'b0;
        ov_tsmp_subtype                  <= 8'b0 ;
        descriptor_extract_state         <= IDLE_S;
        end
    else begin
        case(descriptor_extract_state)
            IDLE_S:begin
                ov_descriptor       <= 12'b0     ;//{iv_ipv,9'b0};  
                o_descriptor_valid  <= 1'b0      ; 
                
                ov_eth_type         <= 16'b0     ;
                ov_tsmp_subtype     <= 8'b0      ;
                if((i_data_wr == 1'b1) && (iv_data[8] == 1'b1))begin//head
                    ov_data                         <= iv_data   ;
                    o_data_wr                       <= 1'b1      ;
                                                                 
                    rv_byte_cnt                     <= 4'b1      ;
                                                                 
                    descriptor_extract_state        <= EXTRACT_INFO_S;
				end
				else begin
					ov_data                         <= 9'b0;
					o_data_wr                       <= 1'b0;
                    
                    rv_byte_cnt                     <= 4'b0;
					descriptor_extract_state        <= IDLE_S;
				end
			end
            EXTRACT_INFO_S:begin
                ov_data                      <= iv_data;
                o_data_wr                    <= i_data_wr;
                
                rv_byte_cnt                  <= rv_byte_cnt + 1'b1;
                if(rv_byte_cnt == 4'd12)begin
                    ov_eth_type                 <= {iv_data[7:0],8'b0}    ;
                    descriptor_extract_state    <= EXTRACT_INFO_S;
                end
                else if(rv_byte_cnt == 4'd13)begin
                    ov_eth_type                 <= {ov_eth_type[15:8],iv_data[7:0]}    ;
                    descriptor_extract_state    <= EXTRACT_INFO_S;
                end
                else if(rv_byte_cnt == 4'd14)begin
                    descriptor_extract_state    <= TRAN_PKT_S;
                    o_descriptor_valid          <= 1'b1;
                    if(ov_eth_type == 16'h8100)begin
                        if(iv_data[6] == 1'b0)begin//st
                            ov_descriptor[11:9]         <= 3'h7  ;//ipv
                            ov_descriptor[8:0]          <= 9'h00 ;//bufid
                        end
                        else begin//rc
                            ov_descriptor[11:9]         <= 3'h4  ;//ipv
                            ov_descriptor[8:0]          <= 9'h00 ;//bufid
                        end
                    end
                    else if(ov_eth_type == 16'hff01)begin
                        ov_descriptor[11:9]         <= 3'h2          ;//ipv
                        ov_descriptor[8:0]          <= 9'h00         ;//bufid
                        ov_tsmp_subtype             <= iv_data[7:0]  ;
                    end
                    else begin
                        ov_descriptor[11:9]         <= 3'h0  ;//ipv
                        ov_descriptor[8:0]          <= 9'h00 ;//bufid                 
                    end
                end                  
                else begin//invalid
                    descriptor_extract_state    <= EXTRACT_INFO_S;
                end            
            end
            TRAN_PKT_S:begin         
                ov_data                   <= iv_data  ;
                o_data_wr                 <= i_data_wr;
                
                ov_descriptor             <= 12'b0;
                o_descriptor_valid        <= 1'b0 ;
                //state judge
                if(i_data_wr == 1'b1 && iv_data[8] ==  1'b1)begin//tail
                    descriptor_extract_state    <= IDLE_S;
                end
                else if(i_data_wr == 1'b1 && iv_data[8] ==  1'b0)begin//middle
                    descriptor_extract_state    <= TRAN_PKT_S;
                end
                else begin//invalid
                    descriptor_extract_state    <= IDLE_S;
                end
            end

            default:begin
                ov_data                         <= 9'b0;
                o_data_wr                       <= 1'b0;
                o_descriptor_valid              <= 1'b0;
                ov_descriptor                   <= 12'b0;
                ov_eth_type                     <= 16'b0;
                ov_tsmp_subtype                 <= 8'b0;
                rv_byte_cnt                     <= 4'b0;
                descriptor_extract_state        <= IDLE_S;
            end
        endcase
    end
endmodule